package cn.itcast.demo;

import org.apache.lucene.document.Document;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.queryparser.classic.ParseException;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.*;
import org.apache.lucene.search.highlight.*;
import org.apache.lucene.search.highlight.Scorer;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.junit.Test;
import org.wltea.analyzer.lucene.IKAnalyzer;

import java.io.File;
import java.io.IOException;

public class LuceneIndexSuperQuery {


    @Test
    public void highLight() throws IOException, ParseException, InvalidTokenOffsetsException {
        //先去索引库中加载所有的数据
        Directory directory = FSDirectory.open(new File("indexDir"));

        //加载索引数据到内存
        IndexReader indexReader = DirectoryReader.open(directory);

        //把加载到的索引数据放到内存中，以供查询

        //索引的检索
        IndexSearcher searcher = new IndexSearcher(indexReader);


        //高亮查询的字段理论上必须要分词
        QueryParser queryParser = new QueryParser("title", new IKAnalyzer());

        Query query = queryParser.parse("谷歌地图");


        //query 查询条件，n表示要查询多少个，手机100万个n是5表示只显示5个
        TopDocs topDocs = searcher.search(query, Integer.MAX_VALUE);

        //命中的个数，实际展示的个数取决于命中的个数和用户设置的需求的个数如果命中的大于需求的，以需求的为准，如果命中的小于需求的则以命中的为准
        int totalHits = topDocs.totalHits;

        System.out.println("总共命中了 = " + totalHits + " 个");

        //获取到得分文档的数组，不过数组中只包含了文档的编号和文档得分，得分用来排序
        ScoreDoc[] scoreDocs = topDocs.scoreDocs;

        //准备高亮工具
        Formatter formatter = new SimpleHTMLFormatter("<em>", "</em>");

        Scorer scorer = new QueryScorer(query);

        Highlighter highlighter = new Highlighter(formatter, scorer);

        //高亮就是对查询的结果进行二次分词
        for (ScoreDoc scoreDoc : scoreDocs) {
            System.out.println("====================================");
            //文档的id
            int docId = scoreDoc.doc;
            //文档的得分
            float score = scoreDoc.score;

            Document doc = searcher.doc(docId);
            String id = doc.get("id");

            String titleResult = doc.get("title");

            //要对之前查询的结果title进行二次分词，在关键字前后拼接标签
            String title = highlighter.getBestFragment(new IKAnalyzer(), "title", titleResult);

            System.out.println("当前文档的得分为：" + score + " id为：" + id + " title为:" + title);
        }
    }


    @Test
    public void sortQuery() throws IOException, ParseException, InvalidTokenOffsetsException {
        //先去索引库中加载所有的数据
        Directory directory = FSDirectory.open(new File("indexDir"));

        //加载索引数据到内存
        IndexReader indexReader = DirectoryReader.open(directory);

        //把加载到的索引数据放到内存中，以供查询

        //索引的检索
        IndexSearcher searcher = new IndexSearcher(indexReader);


        //高亮查询的字段理论上必须要分词
        QueryParser queryParser = new QueryParser("title", new IKAnalyzer());

        Query query = queryParser.parse("谷歌地图");


        //创建一个排序的条件对象
        Sort sort = new Sort(new SortField("id", SortField.Type.LONG));

        //query 查询条件，n表示要查询多少个，手机100万个n是5表示只显示5个
        TopDocs topDocs = searcher.search(query, Integer.MAX_VALUE, sort);

        //命中的个数，实际展示的个数取决于命中的个数和用户设置的需求的个数如果命中的大于需求的，以需求的为准，如果命中的小于需求的则以命中的为准
        int totalHits = topDocs.totalHits;

        System.out.println("总共命中了 = " + totalHits + " 个");

        //获取到得分文档的数组，不过数组中只包含了文档的编号和文档得分，得分用来排序
        ScoreDoc[] scoreDocs = topDocs.scoreDocs;


        //高亮就是对查询的结果进行二次分词
        for (ScoreDoc scoreDoc : scoreDocs) {
            System.out.println("====================================");
            //文档的id
            int docId = scoreDoc.doc;
            //文档的得分
            float score = scoreDoc.score;

            Document doc = searcher.doc(docId);
            String id = doc.get("id");

            String titleResult = doc.get("title");

            System.out.println("当前文档的得分为：" + score + " id为：" + id + " title为:" + titleResult);
        }
    }


    @Test
    public void pageQuery() throws IOException, ParseException, InvalidTokenOffsetsException {


        int page = 4;
        final int PAGE_SIZE = 2;

        int start = (page - 1) * PAGE_SIZE;

        int end = page * PAGE_SIZE;

        //先去索引库中加载所有的数据
        Directory directory = FSDirectory.open(new File("indexDir"));

        //加载索引数据到内存
        IndexReader indexReader = DirectoryReader.open(directory);

        //把加载到的索引数据放到内存中，以供查询

        //索引的检索
        IndexSearcher searcher = new IndexSearcher(indexReader);


        //高亮查询的字段理论上必须要分词
        QueryParser queryParser = new QueryParser("title", new IKAnalyzer());

        Query query = queryParser.parse("谷歌地图");


        //创建一个排序的条件对象
        Sort sort = new Sort(new SortField("id", SortField.Type.LONG));

        //query 查询条件，n表示要查询多少个，手机100万个n是5表示只显示5个
        TopDocs topDocs = searcher.search(query, Integer.MAX_VALUE, sort);

        //命中的个数，实际展示的个数取决于命中的个数和用户设置的需求的个数如果命中的大于需求的，以需求的为准，如果命中的小于需求的则以命中的为准
        int totalHits = topDocs.totalHits;

        System.out.println("总共命中了 = " + totalHits + " 个");

        //获取到得分文档的数组，不过数组中只包含了文档的编号和文档得分，得分用来排序
        ScoreDoc[] scoreDocs = topDocs.scoreDocs;

        //实际总量
        int total = scoreDocs.length;

        //计算分页的总页数
        int totalPage = total % PAGE_SIZE == 0 ? total / PAGE_SIZE : total / PAGE_SIZE + 1;

        if (page>totalPage){
            System.out.println("我总共有:"+totalPage+" 页，你要的太多了，客官不可以");
            return;
        }else if (page==totalPage){//最后一页
            end = total;//结尾的点不应该算应该根据实际情况，查到多少，显示多少

        }


        for (int i = start; i < end; i++) {
            ScoreDoc scoreDoc = scoreDocs[i];
            System.out.println("====================================");
            //文档的id
            int docId = scoreDoc.doc;
            //文档的得分
            float score = scoreDoc.score;

            Document doc = searcher.doc(docId);
            String id = doc.get("id");

            String titleResult = doc.get("title");

            System.out.println("当前文档的得分为：" + score + " id为：" + id + " title为:" + titleResult);
        }

    }


}
